import { createApp, watch } from 'vue';
import MessageBoxComponent from './MessageBox';

export const fields = ['confirm', 'prompt'];

//vue2.x 里的Vue.extend方法可以继承一个新的子类,可以new一个新的应用实例
//vue3.x 可以使用createApp创建应用实例重载到视图
const MessageBox = (options) => {
  const messageBoxApp = createApp(MessageBoxComponent, options);

  //该函数给用户使用时需要链式调用then和catch,所以返回一个Promise对象
  return new Promise((resolve, reject) => {
    showMessageBox(messageBoxApp, { resolve, reject });
  });
};

const showMessageBox = (app, { resolve, reject }) => {
  //将应用实例放到文档碎片再将文档碎片放到body标签里
  const oFrag = document.createDocumentFragment();
  const vm = app.mount(oFrag);

  //这里的应用实例可以获取子组件暴露的属性和方法
  // console.log(vm);
  //Proxy {state: Proxy, setVisible: ƒ}

  document.body.appendChild(oFrag);

  //使用子组件暴露的方法
  vm.setVisible(true);

  //监听实例里的数据 state变更时执行回调
  watch(vm.state, (state) => {
    //当visible=false时
    if (!state.visible) {
      //当点击确定按钮时
      switch (state.type) {
        case 'cancel':
          reject();
          break;
        case 'confirm':
          //打印输入框输入的内容
          // console.log(state.promptValue);
          //抛出输入框的内容
          resolve(state.promptValue);
          break;
        default:
          break;
      }

      //点击完按钮时清除节点
      hideMessageBox(app);
    }
  });
};

//清除消息盒子节点
const hideMessageBox = (app) => {
  app.unmount();
};

fields.forEach((field) => {
  //给MessageBox函数挂载方法
  MessageBox[field] = (options) => {
    options.field = field;

    //执行MessageBox函数可以将当前options.field作为参数传入createApp定义的配置里, 并且返回一个Promise对象
    return MessageBox(options);
  };
});

/**
 console.dir(MessageBox);
 * MessageBox()
 *   confirm: (options) => { options.field = field; }
 *   prompt: (options) => { options.field = field; }
 */

export default MessageBox;
